package domain;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.Vector;

import domain.Paper;

public class Author {
	
	private UUID authorID;
	private String fullName = "";
	private String firstName = "";
	private String lastName = "";
	private String middleName = "";
	private String affiliation = "";
	private String email = "";
	private Vector<Paper> papers;
	private Vector<Author> coauthors;
	private boolean merged = false;
	
	public Author() {
		this.authorID = null;
		this.papers = new Vector<Paper>();
		this.coauthors = new Vector<Author>();
	}
	
	public Author(String first, String second) {
		this();
		this.setFullName(String.format("%s %s", first, second));
	}
	public Author(String name) {
		this();
		this.setFullName(name);
	}

	public Author(UUID authorID, String fullName, String email, String affiliation) {
		this();
		this.authorID = authorID;
		this.setFullName(fullName);
		this.email = email;
		this.affiliation = affiliation;
	}
	
	public Author(UUID fromString) {
		this.authorID = fromString;
	}

	public UUID getAuthorID() {
		return this.authorID;
	}
	
	public void setAuthorID(UUID value) {
		if (this.authorID == null)
			this.authorID = value;
	}
	
	public void setFullName(String value) {
		value = value.trim();
		value = value.replaceAll("\\s+"," ");
		
		this.fullName = value;
		
		// Check if lastname, firstname
		if (value.contains(",")) {
			String[] values = value.split(",");
			value = values[1].trim() + " " + values[0];
		}
		
		String [] values = value.split(" ");				// separate into first/mid/last name
		if(values.length==3){
			this.firstName = values[0];
			this.middleName = values[1];
			this.lastName = values[2];
		}
		else if(values.length==2){
			this.firstName = values[0];
			this.lastName = values[1];
		}
		else{
			this.lastName = values[0];
		}
	}

	public String getFullName() {
		return this.fullName;
	}
	
	public String getFirstName() {
		return this.firstName;
	}
	
	public void setFirstName(String value) {
		this.firstName = (value + "").trim();
	}

	public String getMiddleName() {
		return this.middleName;
	}
	
	public void setMiddleName(String value) {
		this.middleName = (value + "").trim();
	}

	public String getLastName() {
		return this.lastName;
	}
	
	public void setLastName(String value) {
		this.lastName = value.trim();
	}

	public String getAffiliation() {
		return this.affiliation;
	}

	public void setAffiliation(String value) {
		this.affiliation = value;
	}

	public String getEmail() {
		return this.email;
	}

	public void setEmail(String email) {
		this.email = email;
	}
	
	public Vector<Paper> getPapers() {
		return this.papers;
	}
	
	public void addPaper(Paper value){
		if (value != null && !this.papers.contains(value))
			this.papers.add(value);
	}

	public void addCoAuthor(Author value) {
		if (value != null && !this.coauthors.contains(value))
			this.coauthors.add(value);
	}
	
	public List<String> getCoAuthorNames() {
		Vector<String> result = new Vector<String>();
		for(Author coauthor : this.coauthors)
			result.add(coauthor.getFullName());
		
		return Collections.unmodifiableList(result);
	}
	
	public List<String> getPaperTitles() {
		Vector<String> result = new Vector<String>();
		for(Paper paper : this.papers)
			result.add(paper.getTitle());
		
		return Collections.unmodifiableList(result);
	}
	

	public static List<AuthorPair> getCoAuthorPairs(Author authorA, Author authorB) throws Exception {
		if (authorA == null)
			throw new Exception("AuthorA may not be null.");
		if (authorB == null)
			throw new Exception("AuthorB may not be null.");
		if (authorA.getAuthorID() == authorB.getAuthorID())
			throw new Exception("AuthorA may not be the same entity as AuthorB.");

		Vector<AuthorPair> result = new Vector<AuthorPair>();
		
		for(Author coauthorA :authorA.coauthors) {
			for(Author coauthorB : authorB.coauthors) {
				if (coauthorA.equals(coauthorB))
					result.add(new AuthorPair(coauthorA, coauthorB));
			}
		}
		
		return result;
	}
	
	@Override
	public String toString() {

		return String.format(
				"AUTHOR: %s\n" + 
				"EMAIL: %s\n" +		
				"AFFILIATION: %s\n" +
				"CO-AUTHORS: %s\n",
				this.getFullName(), 
				(this.getEmail() == null ? "n/a" : this.getEmail()),
				(this.getAffiliation() == null ? "n/a" : this.getAffiliation()),
				(this.getCoAuthorNames().toString().replaceAll("\\[\\]", "")));
	}

	@Override
	public boolean equals(Object obj) {
		if (!Author.class.isInstance(obj))
			return false;
		Author other = (Author)obj;
		return other.getFullName().equalsIgnoreCase(this.getFullName()) &&
				other.getAffiliation().equalsIgnoreCase(this.getAffiliation()) &&
				other.getEmail().equalsIgnoreCase(this.getEmail());
		// TODO: Add any missing comparison objects
	}
}

